#ifndef VECTOR2D_h__
#define VECTOR2D_h__

#include <cassert>
#include <math.h>

template <class FLTYPE> class Vector2D
{
public:

	FLTYPE v[2];

	typedef Vector2D<FLTYPE> Vector2D_FT;

	inline FLTYPE &x() {return v[0];} ;
	inline FLTYPE &y() {return v[1];};
	inline FLTYPE & operator [] ( const int i ){
		assert(i>=0 && i<2);
		return v[i];
	}
	inline const FLTYPE & operator [] ( const int i ) const {
		assert(i>=0 && i<2);
		return v[i];
	}

	inline Vector2D<FLTYPE> ( void ) { }
	inline Vector2D<FLTYPE> ( const FLTYPE nx, const FLTYPE ny){
		v[0] = nx; v[1] = ny;
	}
	inline Vector2D<FLTYPE> ( Vector2D<FLTYPE> const & p)  {   
		v[0]= p.v[0];    v[1]= p.v[1];
	}
	inline Vector2D<FLTYPE> & operator =( Vector2D<FLTYPE> const & p){
		v[0]= p.v[0]; v[1]= p.v[1]; 
		return *this;
	}
	inline Vector2D<FLTYPE> operator + ( Vector2D<FLTYPE> const & p) const { 
		return Vector2D<FLTYPE>( v[0]+p.v[0], v[1]+p.v[1]);
	}
	inline Vector2D<FLTYPE> operator - ( Vector2D<FLTYPE> const & p) const {
		return Vector2D<FLTYPE>( v[0]-p.v[0], v[1]-p.v[1]);
	}
	inline Vector2D<FLTYPE> operator * ( const FLTYPE s ) const {
		return Vector2D<FLTYPE>( v[0] * s, v[1] * s);
	}
	inline Vector2D<FLTYPE> operator / ( const FLTYPE s ) const {
		return Vector2D<FLTYPE>( v[0] / s, v[1] / s);
	}
	inline FLTYPE operator * ( Vector2D<FLTYPE> const & p ) const {
		return ( v[0]*p.v[0] + v[1]*p.v[1]);
	}  

	inline Vector2D<FLTYPE> & operator += ( Vector2D<FLTYPE> const & p){
		v[0] += p.v[0];    v[1] += p.v[1];
		return *this;
	}
	inline Vector2D<FLTYPE> & operator -= ( Vector2D<FLTYPE> const & p){
		v[0] -= p.v[0];    v[1] -= p.v[1]; 
		return *this;
	}
	inline Vector2D<FLTYPE> & operator *= ( const FLTYPE s ){
		v[0] *= s;    v[1] *= s;
		return *this;
	}
	inline Vector2D<FLTYPE> & operator /= ( const FLTYPE s ){
		v[0] /= s;    v[1] /= s;
		return *this;
	}
	inline FLTYPE Length( void ) const {
		return (FLTYPE)(sqrt( (double)(v[0]*v[0] + v[1]*v[1])));
	}
	inline FLTYPE LengthSquared( void ) const{
		return ( v[0]*v[0] + v[1]*v[1]);
	}

	inline bool operator == ( Vector2D<FLTYPE> const & p ) const {
		return (v[0]==p.v[0] && v[1]==p.v[1]);
	} 
	inline bool operator != ( Vector2D<FLTYPE> const & p ) const {
		return ( (v[0]!=p.v[0]) || (v[1]!=p.v[1]) );
	}

	inline FLTYPE Distance( Vector2D<FLTYPE> const & p ) const{
		return (*this-p).Length();
	}

	inline FLTYPE SquaredDistance( Vector2D<FLTYPE> const & p ) const {
		return (*this-p).LengthSquared();
	}	

}; // end class definition

template <class FLTYPE>
inline Vector2D<FLTYPE> operator - ( Vector2D<FLTYPE> const & p ){
	return Vector2D<FLTYPE>( -p.v[0], -p.v[1]);
}

template <class FLTYPE>
inline Vector2D<FLTYPE> operator * ( const FLTYPE s, Vector2D<FLTYPE> const & p ){
	return Vector2D<FLTYPE>( p.v[0] * s, p.v[1] * s);
}

template <class FLTYPE>
inline FLTYPE Length( Vector2D<FLTYPE> const & p ){
	return sqrt( p.v[0]*p.v[0] + p.v[1]*p.v[1]);
}

template <class FLTYPE>
inline FLTYPE LengthSquared( Vector2D<FLTYPE> const & p ){
	return ( p.v[0]*p.v[0] + p.v[1]*p.v[1]);
}

template <class FLTYPE>
inline FLTYPE Distance( Vector2D<FLTYPE> const & p1,Vector2D<FLTYPE> const & p2 ){
	return Length(p1-p2);
}


typedef Vector2D<short>  Vector2Ds;
typedef Vector2D<int>	   Vector2Di;
typedef Vector2D<float>  Vector2Df;
typedef Vector2D<double> Vector2Dd;

#endif // POSITION_h__